﻿package  
{
	import flash.display.*;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	
	/**
	 * Line2 ジェネレーター
	 */
	public class Line2 extends Sprite
	{
		
		private var _pts :/*Point*/Array
		
		private var _now :int;
		private var _len :int;
		
		private var _num :int;	// 長さ
		private var _sp  :int;	// スピード
		
		
		private var _lb :Number;	// 線の初期太さ
		private var _ld :Number;	// 線の変化量
		private var _seg :uint;		// 分割数
		
		private var _col :uint;		// 色
		
		public function Line2 ( pts :/*Point*/Array = null, lb :Number = 1, ld :Number = 0, col :uint = 0xffffff, seg :uint = 30  ) 
		{
			setPts( pts );
			
			_lb = lb;
			_ld = ld;
			_col = col;
			_seg = seg;
			
			// filters = [ new GlowFilter(0xff00ff), new BlurFilter(0, 0, 1) ]
			
			// filters = [ new GlowFilter(), new BlurFilter(3, 3) ]
			// filters = [ new BlurFilter(3,3) ]
		}
		
		/* Point をセット。何もないと、デフォルト値が入る */
		public function setPts ( pts :/*Point*/Array = null ) 
		{
			if ( pts )
			{
				if ( pts[0] is Point )	_pts = pts;
				else					_pts = Utils.numToPts( pts );
			}
			else		_pts = Data.getPoints();
		}
		/* Point を追加。 */ 
		public function addPts ( pts :/*Point*/Array ) 
		{
			if ( pts[0] is Point )	_pts = _pts.concat( pts );
			else					_pts = _pts.concat( Utils.numToPts( pts ) );
		}
		/* 太さ,  太くなるスピード, 色, 分割数 */ 
		public function setParam ( lb :Number = 1, ld :Number = 0, col :uint = 0xffffff, seg :uint = 30 ) :void
		{
			_lb = lb;
			_ld = ld;
			_col = col;
			_seg = seg;
		}
		
		/* 持続長さ, スピード調整 */
		public function start ( num :int = 50, sp :int = 5 ) :void
		{
			_now = 0;
			_len = _pts.length;
			
			_num = num;		// 持続長さ
			_sp  = sp;		// スピード調整
			
			removeEventListener( Event.ENTER_FRAME, _enterFrame );
			addEventListener( Event.ENTER_FRAME, _enterFrame );
		}
		/* 停止 */
		public function stop ( ) :void
		{
			removeEventListener( Event.ENTER_FRAME, _enterFrame );
		}
		
		private function _enterFrame ( evt :Event ) :void
		{
			var n :int = _now - _num;
			if ( n < 0 ) n = 0;
			
			
			graphics.clear();
			
			
			var numSegments :uint = 30;			// 分割数
			
			// var b :Number = _lb;
			// graphics.lineStyle( b, _col );
			
			if ( n < _len )	graphics.moveTo( _pts[n].x, _pts[n].y );
			
			for ( var i :int = n+1; i < _now && i < _len - 3; i ++ )
			{
				
				var p0:Point = _pts[i];
				var p1:Point = _pts[i + 1];
				var p2:Point = _pts[i + 2];
				var p3:Point = _pts[i + 3];
				
				splineTo( p0, p1, p2, p3, numSegments );
				
				//graphics.lineStyle( b, _col );
				//graphics.lineTo( _pts[i].x, _pts[i].y );
				//b += _ld;
			}
			
			if ( _now < _len + _num + 5 )
			{
				_now += _sp;
			}
			else
			{
				_now = 0;
			}
			
		}
		
		private function splineTo ( p0 :Point, p1 :Point, p2 :Point, p3 :Point, numSegments :uint ) :void
		{
				
		  graphics.lineStyle( _lb , _col );
		  graphics.moveTo( p1.x, p1.y );
		  
		  for( var i:uint=0; i < numSegments; i ++ )
		  {
			var t :Number = (i + 1) / numSegments;
			
			var px :Number = catmullRom( p0.x, p1.x, p2.x, p3.x, t );
			var py :Number = catmullRom( p0.y, p1.y, p2.y, p3.y, t );
			
			graphics.lineTo( px, py );
		  }
		}
		
		private function catmullRom ( p0 :Number, p1 :Number, p2 :Number, p3 :Number, t :Number ) :Number
		{
			var v0:Number = (p2 - p0) * 0.5;
			var v1:Number = (p3 - p1) * 0.5;
			
			return (2*p1 - 2*p2 + v0 + v1)*t*t*t + (-3*p1 + 3*p2 - 2*v0 - v1)*t*t + v0*t + p1;
		}
		
	}
}